package com.echatim.service.app;

import com.annotation.MethodFor;
import com.annotation.TopicFor;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.broker.base.IBrokerStorage;
import com.broker.base.auth.TokenProvider;
import com.broker.base.auth.UserJwt;
import com.broker.base.protocol.hook.UserLoginForm;
import com.broker.base.protocol.response.Resp;
import com.broker.base.storage.BrokerStorageEntry;
import com.broker.utils.strorage.StorageFactory;
import com.commom.AppRespError;
import com.commom.Topic;
import com.echatim.broker.storage.AppStorageEntry;
import com.echatim.broker.storage.event.LoginEventMessage;
import com.echatim.entity.User;
import com.echatim.mapper.UserMapper;
import com.event.EventBus;
import com.utils.Beans;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;

import javax.validation.Valid;

/**
 * @author Daizhiqiang <zqdai@sailfish.com.cn>
 * create by 2020/2/21 13:21
 * Description: mybatisplus-spring-boot
 **/


@Slf4j
@TopicFor(value = Topic.CONNECTION.name)
@ConditionalOnProperty(name="echatim.sdk.auth-type", havingValue="community")
@Service
public class LoginService extends ServiceImpl<UserMapper, User> {
    @Autowired
    private UserService userService;
    @Autowired
    private SdkAppService sdkAppService;
    @Value("${broker.machineId}")
    private String machineId;
    @Autowired
    private EventBus eventBus;


    @MethodFor(value = Topic.CONNECTION.METHOD.AUTHORITY_REQUEST, consumer = UserLoginForm.class)
    public Resp<String> authority(@Valid UserLoginForm userLoginForm){
        IBrokerStorage brokerStorage = getStorage();
        String userInfo = brokerStorage.getValue(AppStorageEntry.CLIENT_USER_INFO, userLoginForm.getAuid(), ()->{
            User user =  userService.lambdaQuery()
                    .eq(User::getAuid, userLoginForm.getAuid())
                    .eq(User::getToken, userLoginForm.getToken())
                    .one();
            return user != null ? Beans.json(user) : null;
        });
        if(Beans.strEmpty(userInfo)){
            return Resp.failed(AppRespError.CLIENT_LOGIN);
        }
        Resp<Void> sdkVerified = sdkAppService.verifySDKKey(userLoginForm.getAppKey());
        if(!sdkVerified.ok()){
            return Resp.failed(sdkVerified.getMsg());
        }


        // 用户认证收集器
        if(Beans.strNotEmpty(userLoginForm.getClientId())){
            IBrokerStorage storage = StorageFactory.getInstance();
            storage.getAllKeyValues(BrokerStorageEntry.CLIENT_TO_LOGINUSER).forEach((k, v)->{
                if(v.equals(userLoginForm.getAuid())){
                    storage.remove(BrokerStorageEntry.CLIENT_TO_LOGINUSER, k); // 删除用户之前连接的客户端信息
                }
            });
            storage.setKeyValue(BrokerStorageEntry.CLIENT_TO_LOGINUSER, userLoginForm.getClientId(), userLoginForm.getAuid());
        }

        TokenProvider token = new TokenProvider();
        String jwt = token.createToken(new UserJwt()
                .setAuid(userLoginForm.getAuid())
                .setAppKey(userLoginForm.getAppKey()));
//        topicSender.getSender().send(Beans.copy(userLoginForm, LoginEventMessage.class));
        eventBus.post(Beans.copy(userLoginForm, LoginEventMessage.class)); // 发送本机事件

        return Resp.ok(jwt);
    }

    private IBrokerStorage getStorage(){
        return StorageFactory.getInstance();
    }


    public Resp<String> login(UserLoginForm userLoginForm) {
        User user =  userService.lambdaQuery()
                .eq(User::getAuid, userLoginForm.getAuid())
                .eq(User::getToken, userLoginForm.getToken())
                .one();
        if(user == null){
            return Resp.failed(AppRespError.CLIENT_LOGIN);
        }
        TokenProvider token = new TokenProvider();
        String jwt = token.createToken(new UserJwt()
                .setAuid(userLoginForm.getAuid())
                .setAppKey(userLoginForm.getAppKey()));

        return Resp.ok(jwt);
    }
}

